#include "MyGlWindow.h"
#include "vertex.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QDebug>

#define MY_GL_FUNC  context()->extraFunctions()


static const GLuint  NumVertices = 6;
static const QVector3D color(0.5f, 0.5f, 0.0f);

static Vertex  vertices[NumVertices] = {
    Vertex( QVector3D(-0.90f, -0.90f, 0.0f),color),
    Vertex( QVector3D(0.85f, -0.90f, 0.0f), color),
    Vertex( QVector3D(-0.90f,  0.85f, 0.0f),color),
    Vertex( QVector3D(0.90f, -0.85f, 0.0f), color),
    Vertex( QVector3D(0.90f,  0.90f, 0.0f), color),
    Vertex( QVector3D(-0.85f,  0.90f, 0.0f),color)
};


MyGlWindow::MyGlWindow()
    : program(nullptr)
{}

void MyGlWindow::initializeGL()
{
    if (! MY_GL_FUNC) {
        qCritical("NO support for QOpenGLExtraFunctions!");
        ::exit(0);
    }

    connect(context(), SIGNAL(aboutToBeDestroyed()), SLOT(teardownGL()));
    MY_GL_FUNC->initializeOpenGLFunctions();
    MY_GL_FUNC->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    bool rc = false;

    // create buffer
    buffer = new QOpenGLBuffer;
    rc = buffer->create();
    Q_ASSERT(rc);

    rc = buffer->bind();
    Q_ASSERT(rc);

    //buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
    qDebug() << Q_FUNC_INFO << buffer->usagePattern();
    buffer->allocate(vertices, sizeof(vertices));

    // create VAO
    vao = new QOpenGLVertexArrayObject(this);
    rc = vao->create();
    Q_ASSERT(rc);

    vao->bind();

    // create program
    program = new QOpenGLShaderProgram(this);

    rc = program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert");
    Q_ASSERT(rc);

    rc = program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/simple.frag");
    Q_ASSERT(rc);

    rc = program->link();
    Q_ASSERT(rc);

    rc = program->bind();
    Q_ASSERT(rc);

    program->enableAttributeArray(0);
    program->enableAttributeArray(1);
    program->setAttributeBuffer(0, GL_FLOAT, Vertex::positionOffset(), Vertex::PositionTupleSize, Vertex::stride());
    program->setAttributeBuffer(1, GL_FLOAT, Vertex::colorOffset(), Vertex::ColorTupleSize, Vertex::stride());

    // Release (unbind) all
    program->release();
    vao->release();
    buffer->release();
    printContextInformation();
}

void MyGlWindow::paintGL()
{
    MY_GL_FUNC->glClear(GL_COLOR_BUFFER_BIT);
    bool rc = false;

    rc = program->bind();
    Q_ASSERT(rc);

    vao->bind();
    MY_GL_FUNC->glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    vao->release();
    program->release();
}

void MyGlWindow::teardownGL()
{
    delete program;
    program = nullptr;

    delete vao;
    vao = nullptr;

    delete buffer;
    buffer = nullptr;
}

void MyGlWindow::printContextInformation()
{
  QString glType;
  QString glVersion;
  QString glProfile;

  // Get Version Information
  glType = (context()->isOpenGLES()) ? "OpenGL ES" : "OpenGL";
  glVersion = reinterpret_cast<const char*>(MY_GL_FUNC->glGetString(GL_VERSION));
//  glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));

  // Get Profile Information
#define CASE(c) case QSurfaceFormat::c: glProfile = #c; break
  switch (format().profile())
  {
    CASE(NoProfile);
    CASE(CoreProfile);
    CASE(CompatibilityProfile);
  }
#undef CASE

  // qPrintable() will print our QString w/o quotes around it.
  qDebug() << qPrintable(glType) << qPrintable(glVersion) << "(" << qPrintable(glProfile) << ")";
}
